package com.luyuan.crm.sale.web;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.annotation.Resource;
import javax.faces.component.UIInput;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;
import javax.faces.model.DataModel;
import javax.faces.model.ListDataModel;

import org.springframework.beans.factory.InitializingBean;

import com.luyuan.crm.member.model.Address;
import com.luyuan.crm.member.model.Customer;
import com.luyuan.crm.member.model.Member;
import com.luyuan.crm.member.model.MemberCoupon;
import com.luyuan.crm.member.model.MemberCouponType;
import com.luyuan.crm.member.model.MemberIntegral;
import com.luyuan.crm.member.model.NoAccountCustomer;
import com.luyuan.crm.member.model.Region;
import com.luyuan.crm.member.service.CustomerService;
import com.luyuan.crm.member.service.MemberIntegralService;
import com.luyuan.crm.member.service.RegionService;
import com.luyuan.crm.product.model.Product;
import com.luyuan.crm.promotion.Promotion;
import com.luyuan.crm.promotion.PromotionModel;
import com.luyuan.crm.promotion.PromotionModelCash;
import com.luyuan.crm.promotion.PromotionModelCashIntegral;
import com.luyuan.crm.promotion.PromotionModelIntegral;
import com.luyuan.crm.promotion.PromotionModelN4M;
import com.luyuan.crm.promotion.PromotionModelReduction;
import com.luyuan.crm.promotion.PromotionService;
import com.luyuan.crm.sale.model.Delivery;
import com.luyuan.crm.sale.model.Order;
import com.luyuan.crm.sale.model.OrderProduct;
import com.luyuan.crm.sale.model.OrderPromotion;
import com.luyuan.crm.sale.model.OrderType;
import com.luyuan.crm.sale.service.OrderProductService;
import com.luyuan.crm.sale.service.OrderService;
import com.luyuan.crm.user.Party;
import com.luyuan.crm.user.service.PartyService;
import com.ruijie.components.security.model.AppUser;
import com.ruijie.foundation.dao.support.HibernateUtils;
import com.ruijie.foundation.exception.BusinessException;
import com.ruijie.foundation.international.MessageFormat;
import com.ruijie.foundation.security.AppUserContext;
import com.ruijie.util.StringUtils;
import com.ruijie.web.jsf.action.BaseAction;
import com.ruijie.web.jsf.action.WizardAction;
import com.ruijie.web.jsf.context.WizardScope;

public class BaseOrderWizardAction extends BaseAction implements WizardAction, InitializingBean {

    @Resource(name = "customerService")
    protected CustomerService customerService;

    @Resource(name = "partyService")
    protected PartyService partyService;

    @Resource(name = "memberIntegralService")
    protected MemberIntegralService memberIntegralService;

    @Resource(name = "orderService")
    protected OrderService orderService;

    @Resource(name = "orderProductService")
    protected OrderProductService orderProductService;

    @Resource(name = "regionService")
    private RegionService regionService;

    @Resource(name = "promotionService")
    private PromotionService promotionService;

    protected Order order;

    protected List<OrderProduct> products = new ArrayList<OrderProduct>();

    protected Customer customer;

    protected MemberIntegral memberIntegral;

    /**
     * 原始积分
     */
    protected int currentIntegral = 0;

    protected int oldIntegral = 0;

    public void addProduct(ActionEvent actionEvent) {
        setRequestAttribute("products", products, true);
        setRequestAttribute("member", customer, true);
        setRequestAttribute("order", order, true);
    }

    public void deleteProductById(String id) {
        for (OrderProduct p : products) {
            if (p.getProduct().getId().equals(id)) {
                products.remove(p);
                break;
            }
        }
    }

    public void deleteProducts(ActionEvent event) {
        String[] selectedIds = getRequestParameterValues("product.id");
        if (selectedIds == null) {
            selectedIds = new String[0];
            addGlobalI18nMessage("请至少选择一条数据");
            return;
        }
        for (String id : selectedIds) {
            deleteProductById(id);
        }
    }

    public void saveProduct() {
        if (customer.getId() != null) {
            if (customer.getAddress() == null || StringUtils.isNullOrEmpty(customer.getAddress().getProvince())) {
                customer.setAddress(order.getDelivery().getDeliveryAddress());
            }
            else if (HibernateUtils.resolveRealObject(customer) instanceof Member) {
                customer.setAddress(order.getDelivery().getDeliveryAddress());
                String phone = order.getDelivery().getDeliveryPhone();
                customer.setMobile(phone.split(",|，|、")[0]);
                customer.setName(order.getDelivery().getReceiver());
            }

            customerService.updateCustomer(customer);
        }
        else {
            if (HibernateUtils.resolveRealObject(customer) instanceof Member) {
                NoAccountCustomer accountCustomer = new NoAccountCustomer();
                accountCustomer.setAccountHolder((Member) order.getCustomer());
                if (customer.getAddress() != null) {
                    accountCustomer.setAddress(customer.getAddress());
                }
                else {
                    accountCustomer.setAddress(order.getDelivery().getDeliveryAddress());
                }
                if (StringUtils.isNotEmpty(customer.getMobile())) {
                    accountCustomer.setMobile(customer.getMobile());
                }
                else {
                    String phone = order.getDelivery().getDeliveryPhone();
                    accountCustomer.setMobile(phone.split(",|，|、")[0]);
                }
                if (StringUtils.isNotEmpty(customer.getName())) {
                    accountCustomer.setName(customer.getName());
                }
                else {
                    accountCustomer.setMobile(order.getDelivery().getReceiver());
                }
                accountCustomer.setBirthDate(customer.getBirthDate());
                accountCustomer.setEmail(customer.getEmail());
                accountCustomer.setGender(customer.getGender());
                accountCustomer.setHeight(customer.getHeight());
                accountCustomer.setWeight(customer.getWeight());
                accountCustomer.setQq(customer.getQq());
                accountCustomer.setNativePlace(customer.getNativePlace());

                customerService.addCustomer(accountCustomer);
                customer = accountCustomer;
            }
        }

        Set<OrderProduct> orderProducts = new HashSet<OrderProduct>(products);
        for (OrderProduct pro : products) {
            pro.setOrder(order);
        }
        order.setOrderProducts(orderProducts);

        orderService.createOrder(order);
    }

    public void updateProduct() {
        if (customer.getAddress() == null || StringUtils.isNullOrEmpty(customer.getAddress().getProvince())) {
            customer.setAddress(order.getDelivery().getDeliveryAddress());
        }
        else if (HibernateUtils.resolveRealObject(customer) instanceof Member) {
            customer.setAddress(order.getDelivery().getDeliveryAddress());
            String phone = order.getDelivery().getDeliveryPhone();
            customer.setMobile(phone.split(",|，|、")[0]);
            customer.setName(order.getDelivery().getReceiver());
        }
        // old integeral
        // memberIntegral.setCurrentIntegral(currentIntegral);
        customerService.updateCustomer(customer);

        Set<OrderProduct> orderProducts = order.getOrderProducts();

        List<OrderProduct> list = new ArrayList<OrderProduct>(orderProducts);
        for (OrderProduct orderProduct : list) {
            if (!products.contains(orderProduct)) {
                orderProducts.remove(orderProduct);
                orderProductService.removeOrderProduct(orderProduct);
            }
        }

        for (OrderProduct p : products) {
            if (!orderProducts.contains(p)) {
                p.setOrder(order);
                orderProducts.add(p);
            }
        }

        orderService.updateOrder(order);
    }

    public DataModel getProductTableModel() {
        Collections.sort(products);
        return new ListDataModel(products);
    }

    public void onPromotionChange(ActionEvent event) {
        order.getOrderPromotion().setIntegralDeduction(0);
        order.getOrderPromotion().setCouponDeduction(null);
        computeAmount(event);
    }

    public void computeAmount(ActionEvent actionEvent) {
        computeOldAmount();

        boolean hasGift = false;
        for (OrderProduct p : products) {
            if (p.isGift()) {
                hasGift = true;
                break;
            }
        }

        double oldAmount = order.getOldAmount();
        // 折扣原因
        StringBuffer b = new StringBuffer();
        // 礼品赠送
        if (hasGift) {
            b.append("礼品赠送：含部分赠品。").append("\r\n");
        }
        // 积分兑换
        for (OrderProduct p : products) {
            if (p.getExchangeIntegral() > 0) {
                b.append("积分兑换：").append(p.getExchangeIntegral()).append("兑换").append(p.getName()).append("。\r\n");
            }
        }
        // 减免运费
        if (order.getOrderPromotion().isFreeFreight()) {
            oldAmount -= order.getFreight();
            b.append("减免运费：满300减免运费。").append("\r\n");
        }
        // 促销活动
        Promotion promotion = order.getOrderPromotion().getPromotion();
        if (promotion != null) {
            promotion = promotionService.getPromotionById(promotion.getId());
            b.append("促销活动：").append(promotion.getTheme()).append("。\r\n");
            Set<Product> promotionProducts = promotion.getProducts();
            PromotionModel model = promotion.getModel();
            if (model instanceof PromotionModelN4M) {
                PromotionModelN4M modelN4M = (PromotionModelN4M) model;
                for (Product product : promotionProducts) {
                    for (OrderProduct orderProduct : products) {
                        if (product.equals(orderProduct.getProduct())) {
                            if (modelN4M.getM() <= orderProduct.getCount()) {
                                orderProduct.setGifts(modelN4M.getN() * (orderProduct.getCount() / modelN4M.getM()));
                                b.append("    ").append(orderProduct.getName()).append("：").append("满")
                                        .append(modelN4M.getN() * orderProduct.getCount() / modelN4M.getM())
                                        .append("送")
                                        .append(modelN4M.getN() * (orderProduct.getCount() / modelN4M.getM()))
                                        .append("。\r\n");
                            }
                        }
                    }
                }
            }
            else if (model instanceof PromotionModelReduction) {
                PromotionModelReduction modelReduction = (PromotionModelReduction) model;
                if (modelReduction.getM() <= oldAmount) {
                    int times = (int) (oldAmount / modelReduction.getM());
                    oldAmount -= modelReduction.getN() * times;
                    b.append("    ").append("满").append(modelReduction.getM() * times).append("减")
                            .append(modelReduction.getN() * times).append("。\r\n");
                }
            }
            else if (model instanceof PromotionModelCashIntegral) {
                PromotionModelCashIntegral modelCashIntegral = (PromotionModelCashIntegral) model;
                for (Product product : promotionProducts) {
                    for (OrderProduct orderProduct : products) {
                        if (product.equals(orderProduct.getProduct())) {
                            oldAmount -= orderProduct.getSubTotal() - orderProduct.getSubTotal()
                                    * modelCashIntegral.getDiscount();
                            orderProduct.setSubTotal(orderProduct.getSubTotal() * modelCashIntegral.getDiscount());
                            b.append("    ").append(orderProduct.getName()).append("：")
                                    .append((int) (modelCashIntegral.getDiscount() * 10)).append("折").append("。\r\n");

                            int integral = oldIntegral;
                            int exIntegral = (int) orderProduct.getPrice() * modelCashIntegral.getIntegralTimes();
                            if (integral >= exIntegral) {
                                int count = Math.min(integral / exIntegral, orderProduct.getCount());
                                double reduction = orderProduct.getPrice() * count;
                                oldAmount -= reduction;
                                orderProduct.setSubTotal(orderProduct.getSubTotal() - reduction);
                                oldIntegral = integral - (int) reduction * modelCashIntegral.getIntegralTimes();
                                b.append("    ").append(orderProduct.getName()).append("：")
                                        .append(modelCashIntegral.getIntegralTimes()).append("倍积分兑换")
                                        .append(reduction * modelCashIntegral.getIntegralTimes()).append("积分减免")
                                        .append(reduction).append("元。\r\n");
                            }
                        }
                    }
                }
            }
            else if (model instanceof PromotionModelCash) {
                PromotionModelCash modelCash = (PromotionModelCash) model;
                for (Product product : promotionProducts) {
                    for (OrderProduct orderProduct : products) {
                        if (product.equals(orderProduct.getProduct())) {
                            oldAmount -= orderProduct.getSubTotal() - orderProduct.getSubTotal()
                                    * modelCash.getDiscount();
                            orderProduct.setSubTotal(orderProduct.getSubTotal() * modelCash.getDiscount());
                            b.append("    ").append(orderProduct.getName())
                                    .append((int) (modelCash.getDiscount() * 10)).append("折").append("。\r\n");
                        }
                    }
                }
            }
            else if (model instanceof PromotionModelIntegral) {
                PromotionModelIntegral modelIntegral = (PromotionModelIntegral) model;
                for (Product product : promotionProducts) {
                    for (OrderProduct orderProduct : products) {
                        if (product.equals(orderProduct.getProduct())) {
                            int integral = oldIntegral;
                            int exIntegral = (int) orderProduct.getPrice() * modelIntegral.getIntegralTimes();
                            if (integral >= exIntegral) {
                                int count = Math.min(integral / exIntegral, orderProduct.getCount());
                                double reduction = orderProduct.getPrice() * count;
                                oldAmount -= reduction;
                                orderProduct.setSubTotal(orderProduct.getSubTotal() - reduction);
                                oldIntegral = integral - (int) reduction * modelIntegral.getIntegralTimes();
                                b.append("    ").append(orderProduct.getName()).append("：")
                                        .append(modelIntegral.getIntegralTimes()).append("倍积分兑换")
                                        .append(reduction * modelIntegral.getIntegralTimes()).append("积分减免")
                                        .append(reduction).append("元。\r\n");
                            }
                        }
                    }
                }
            }
        }
        // 积分
        int integralDeduction = order.getOrderPromotion().getIntegralDeduction();
        if (integralDeduction > 0) {
            int a = integralDeduction / 500 * 30;
            oldAmount -= a;
            b.append("积分抵扣：").append(integralDeduction).append("抵扣").append(a).append("元。\r\n");
        }
        // A/B卷
        MemberCoupon coupon = order.getOrderPromotion().getCouponDeduction();
        if (coupon != null && coupon.getAmount() > 0) {
            b.append("A/B卷抵扣：");
            if (coupon.getCouponType() == MemberCouponType.A) {
                oldAmount -= coupon.getAmount();
                b.append("A券抵").append(coupon.getAmount()).append("元。\r\n");
            }
            else if (coupon.getCouponType() == MemberCouponType.B) {
                oldAmount -= 300;
                b.append("B券满1000元抵300元。").append("\r\n");
            }
        }
        // 会员折扣
        if (order.getOrderPromotion().isMemberDiscount()) {
            double discount = memberIntegral.getDiscount();
            oldAmount = Math.round(oldAmount * discount);
            b.append("会员折扣：").append(
                    MessageFormat.format("luyuan_crm_member_memberLevel_" + memberIntegral.getMemberLevel().name()));
            b.append("").append(discount * 10).append("折。").append("\r\n");
        }
        // 赠送积分
        b.append("赠送积分：").append(oldAmount).append("。\r\n");
        // 赠送A、B卷
        if ((int) (oldAmount / 500) > 0) {
            b.append("赠送A卷：").append((int) (oldAmount / 500) * 100).append("，一个月内使用有效。\r\n");
        }
        if (oldAmount > 300) {
            b.append("赠送B卷：300，一个月内使用有效。\r\n");
        }
        order.setRemarks(b.toString());

        order.setAmount(Math.round(oldAmount));
    }

    private void computeOldAmount() {
        double result = order.getFreight();
        int exchangeIntegral = 0;
        for (OrderProduct pro : products) {
            pro.setName(pro.getProduct().getName());
            pro.setSpecification(pro.getProduct().getSpecification());
            pro.setPrice(pro.getProduct().getPrice());
            pro.setGifts(0);

            double price = pro.getProduct().getPrice();
            int count = pro.getCount();
            if (pro.isGift()) {
                pro.setSubTotal(0);
            }
            else {
                pro.setSubTotal(price * count);
            }

            if (pro.getExchangeIntegral() > 0) {
                exchangeIntegral += pro.getExchangeIntegral();
            }
            else {
                result += pro.getSubTotal();
            }
        }

        if (memberIntegral.getMemberLevel() != null) {
            int integral = this.currentIntegral - exchangeIntegral;
            if (integral < 0) {
                throw new BusinessException("积分不足！");
            }
            oldIntegral = integral;
        }
        order.setOldAmount(Math.round(result));
    }

    @Override
    public void doCompelete() {
        // 保存单品的订单
        if (order.getId() != null) {
            updateProduct();
            return;
        }
        saveProduct();
    }

    @Override
    public void setActionType(String s) {
    }

    @Override
    public void setStepName(String s) {
        if ("luyuan_crm_sale_confirm_order".equals(s)) {
            computeAmount(null);
        }
        else if ("luyuan_crm_sale_write_question".equals(s)) {
            if (StringUtils.isNullOrEmpty(customer.getName())) {
                customer.setName(order.getDelivery().getReceiver());
                customer.setMobile(order.getDelivery().getDeliveryPhone());
            }
            customer.setAddress(order.getDelivery().getDeliveryAddress());
        }
    }

    @Override
    public String getStepName() {
        return null;
    }

    @Override
    public void setWizardName(String s) {
    }

    @Override
    public String getWizardName() {
        return null;
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        order = (Order) getRequestAttribute("order");
        if (order != null) {
            orderService.refresh(order);
            order.getDelivery().getDeliveryPhone();
            customer = customerService.getById(order.getCustomer().getId());
            customer.getAddress().getCity();
            memberIntegral = memberIntegralService.getMemberIntegral(order.getCustomer());
            currentIntegral = memberIntegral.getCurrentIntegral();
            if (order.getOrderPromotion() != null) {
                currentIntegral += order.getOrderPromotion().getIntegralDeduction();
            }
            else {
                order.setOrderPromotion(new OrderPromotion());
                order.getOrderPromotion().setOrder(order);
            }
            WizardScope.put("customer", customer);
            WizardScope.put("order", order);
            WizardScope.put("memberIntegral", memberIntegral);
            WizardScope.put("order.couponDeduction", order.getOrderPromotion().getCouponDeduction());
            WizardScope.put("orderProducts", products);

            products.addAll(order.getOrderProducts());
            for (OrderProduct product : products) {
                product.getProduct().getName();
                if (product.getExchangeIntegral() > 0) {
                    currentIntegral += product.getExchangeIntegral();
                }
            }

            oldIntegral = currentIntegral;
            return;
        }

        // 新建订单
        order = new Order();
        order.setOrderType(OrderType.SINGLE_PRODUCT);
        order.setDelivery(new Delivery());
        order.setOrderPromotion(new OrderPromotion());
        order.getOrderPromotion().setOrder(order);

        // 归属分公司
        AppUser appUser = (AppUser) AppUserContext.getCurrentUser();
        Party party = partyService.getByAppUser(appUser);
        order.setBranchOffice(party.getBranchOffice());

        customer = (Customer) getRequestAttribute("customer");
        if (HibernateUtils.resolveRealObject(customer) instanceof NoAccountCustomer) {
            order.setCustomer(((NoAccountCustomer) customer).getAccountHolder());
        }
        else {
            order.setCustomer(customer);
        }
        memberIntegral = memberIntegralService.getMemberIntegral(order.getCustomer());
        oldIntegral = currentIntegral = memberIntegral.getCurrentIntegral();

        WizardScope.put("customer", customer);
        WizardScope.put("order", order);
        WizardScope.put("memberIntegral", memberIntegral);
        WizardScope.put("orderProducts", products);

        onCustomerChange();
    }

    public void onCustomerChange() {
        if (customer == null) {
            customer = new Customer();
            customer.setAddress(order.getDelivery().getDeliveryAddress());
            // customer.setName(order.getDelivery().getReceiver());
            // customer.setMobile(order.getDelivery().getDeliveryPhone());
            // customer.setBirthDate(order.getCustomer().getBirthDate());
            // customer.setEmail(order.getCustomer().getEmail());
            // customer.setGender(order.getCustomer().getGender());
            // customer.setHeight(order.getCustomer().getHeight());
            // customer.setWeight(order.getCustomer().getWeight());
            // customer.setQq(order.getCustomer().getQq());
            // customer.setMsn(order.getCustomer().getMsn());
        }

        order.getDelivery().setDeliveryAddress(new Address());
        order.getDelivery().getDeliveryAddress().setCity(customer.getAddress().getCity());
        order.getDelivery().getDeliveryAddress().setPostCode(customer.getAddress().getPostCode());
        order.getDelivery().getDeliveryAddress().setProvince(customer.getAddress().getProvince());
        order.getDelivery().getDeliveryAddress().setRegion(customer.getAddress().getRegion());
        order.getDelivery().getDeliveryAddress().setStreet(customer.getAddress().getStreet());
        order.getDelivery().setReceiver(customer.getName());
        order.getDelivery().setDeliveryPhone(customer.getMobile());
    }

    public Order getOrder() {
        return order;
    }

    public void setOrder(Order order) {
        this.order = order;
    }

    public Customer getCustomer() {
        return customer;
    }

    public MemberIntegral getMemberIntegral() {
        return memberIntegral;
    }

    public int getOldIntegral() {
        return oldIntegral;
    }

    public void setCustomer(Customer customer) {
        if (customer == null && this.customer != null && this.customer.getId() == null) {
            return;
        }
        this.customer = customer;
    }

    public void resetPostCode(ActionEvent event) {
        if (isCustomerEdit()) {
            resetCustomerPostCode();
        }
        else {
            resetDeliveryPostCode();
        }
    }

    private void resetDeliveryPostCode() {
        String province = null, city = null, region = null;
        UIInput uiInput = (UIInput) FacesContext.getCurrentInstance().getViewRoot()
                .findComponent("orderWizard_form:province");
        if (uiInput != null) {
            province = String.valueOf(uiInput.getValue());
        }

        uiInput = (UIInput) FacesContext.getCurrentInstance().getViewRoot().findComponent("orderWizard_form:city");
        if (uiInput != null) {
            city = String.valueOf(uiInput.getValue());
        }

        uiInput = (UIInput) FacesContext.getCurrentInstance().getViewRoot().findComponent("orderWizard_form:region");
        if (uiInput != null) {
            region = String.valueOf(uiInput.getValue());
        }

        Region r = regionService.getByRegion(province, city, region);
        if (r != null) {
            order.getDelivery().getDeliveryAddress().setPostCode(r.getId());
        }
    }

    public void onProvinceChange(ActionEvent event) {
        if (isCustomerEdit()) {
            customer.getAddress().setCity(null);
            customer.getAddress().setRegion(null);
        }
        else {
            order.getDelivery().getDeliveryAddress().setCity(null);
            order.getDelivery().getDeliveryAddress().setRegion(null);
        }
    }

    public void onCityChange(ActionEvent event) {
        if (isCustomerEdit()) {
            customer.getAddress().setRegion(null);
        }
        else {
            order.getDelivery().getDeliveryAddress().setRegion(null);
        }
    }

    private void resetCustomerPostCode() {
        String province = null, city = null, region = null;
        UIInput uiInput = (UIInput) FacesContext.getCurrentInstance().getViewRoot()
                .findComponent("orderWizard_form:province");
        if (uiInput != null) {
            province = String.valueOf(uiInput.getValue());
        }

        uiInput = (UIInput) FacesContext.getCurrentInstance().getViewRoot().findComponent("orderWizard_form:city");
        if (uiInput != null) {
            city = String.valueOf(uiInput.getValue());
        }

        uiInput = (UIInput) FacesContext.getCurrentInstance().getViewRoot().findComponent("orderWizard_form:region");
        if (uiInput != null) {
            region = String.valueOf(uiInput.getValue());
        }

        Region r = regionService.getByRegion(province, city, region);
        if (r != null) {
            order.getDelivery().getDeliveryAddress().setPostCode(r.getId());
        }
    }

    private boolean isCustomerEdit() {
        return null != FacesContext.getCurrentInstance().getViewRoot().findComponent("orderWizard_form:province");
    }

    public boolean isMember() {
        return HibernateUtils.resolveRealObject(order.getCustomer()) instanceof Member;
    }
}
